import { Injectable } from '@angular/core';
import { RisksHttpService } from '@common/api/risks-http.service';
import { AssetsHttpService } from '@common/api/assets-http.service';
import { combineLatest, Observable, of, Subject } from 'rxjs';
import { catchError, map, repeatWhen } from 'rxjs/operators';
import { VulnerabilityProfile, VulnerabilityProfileEntry } from '@common/types';
import { MapConstant } from '@common/constants/map.constant';

@Injectable()
export class VulnerabilityProfileService {
  private refreshSubject = new Subject();
  private entries = [];

  constructor(
    private risksHttpService: RisksHttpService,
    private assetsHttpService: AssetsHttpService
  ) {}

  initVulnerabilityProfile() {
    return combineLatest([this.getProfiles(), this.getDomains()]).pipe(
      map(([profiles, domains]) => {
        return {
          profiles,
          domains,
        };
      }),
      repeatWhen(() => this.refreshSubject)
    );
  }

  deleteProfile(name: string, entry: string) {
    return this.risksHttpService.deleteCVEProfile(name, entry);
  }

  addEntry(config: VulnerabilityProfile) {
    return this.risksHttpService.postCVEProfile(config);
  }

  updateEntry(config: VulnerabilityProfileEntry, name: string) {
    return this.risksHttpService.patchCVEProfile(config, name);
  }

  refresh() {
    this.refreshSubject.next();
  }

  private getProfiles(): Observable<VulnerabilityProfileEntry[]> {
    return this.risksHttpService.getCVEProfile().pipe(
      map(profile => {
        return profile.profiles[0]?.entries || [];
      }),
      catchError(err => {
        if (
          [MapConstant.NOT_FOUND, MapConstant.ACC_FORBIDDEN].includes(
            err.status
          )
        ) {
          return of([]);
        } else {
          throw err;
        }
      })
    );
  }

  private getDomains(): Observable<string[]> {
    return this.assetsHttpService.getDomain().pipe(
      map(data => {
        return data.domains
          .map(domain => domain.name)
          .filter(domain => domain.charAt(0) !== '_');
      }),
      catchError(err => {
        if (
          [MapConstant.NOT_FOUND, MapConstant.ACC_FORBIDDEN].includes(
            err.status
          )
        ) {
          return of([]);
        } else {
          throw err;
        }
      })
    );
  }
}
